
#ifndef _MCUDRIVERS_DMA_H
#define _MCUDRIVERS_DMA_H

#include <xc.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>


typedef enum 
{
    DMA_CHANNEL_0 =  0,       
    DMA_CHANNEL_1 =  1,       
    DMA_CHANNEL_2 =  2,       
    DMA_CHANNEL_3 =  3,       
    DMA_NUMBER_OF_CHANNELS = 4
} DMA_CHANNEL;

void DMA_Initialize_g(void);

inline static void DMA_FlagInterruptClear(DMA_CHANNEL  channel)
{    
    switch(channel) { 
        case DMA_CHANNEL_0:
                IFS0bits.DMA0IF = 0;                
                break;       
        case DMA_CHANNEL_1:
                IFS0bits.DMA1IF = 0;                
                break;       
        case DMA_CHANNEL_2:
                IFS1bits.DMA2IF = 0;                
                break;       
        case DMA_CHANNEL_3:
                IFS2bits.DMA3IF = 0;                
                break;       
        default:break;
         
    }
}

inline static void DMA_InterruptEnable(DMA_CHANNEL  channel)
{    
    switch(channel) { 
        case DMA_CHANNEL_0:
                IEC0bits.DMA0IE = 1;                
                break;       
        case DMA_CHANNEL_1:
                IEC0bits.DMA1IE = 1;                
                break;       
        case DMA_CHANNEL_2:
                IEC1bits.DMA2IE = 1;                
                break;       
        case DMA_CHANNEL_3:
                IEC2bits.DMA3IE = 1;                
                break;       
        default:break;
         
    }
}

inline static void DMA_InterruptDisable(DMA_CHANNEL  channel)
{    
    switch(channel) {        
        case DMA_CHANNEL_0:
                IEC0bits.DMA0IE = 0;                
                break;       
        case DMA_CHANNEL_1:
                IEC0bits.DMA1IE = 0;                
                break;       
        case DMA_CHANNEL_2:
                IEC1bits.DMA2IE = 0;                
                break;       
        case DMA_CHANNEL_3:
                IEC2bits.DMA3IE = 0;                
                break;       
        default:break;
    }
}
    
inline static void DMA_ChannelEnable(DMA_CHANNEL  channel)
{
    switch(channel) {
        case DMA_CHANNEL_0:
                DMA0CONbits.CHEN = 1;
                break;     
        case DMA_CHANNEL_1:
                DMA1CONbits.CHEN = 1;
                break;     
        case DMA_CHANNEL_2:
                DMA2CONbits.CHEN = 1;
                break;     
        case DMA_CHANNEL_3:
                DMA3CONbits.CHEN = 1;
                break;     
        default: break;
    }
}
    
inline static void DMA_ChannelDisable(DMA_CHANNEL  channel)
{
    switch(channel) {
        case DMA_CHANNEL_0:
                DMA0CONbits.CHEN = 0;
                break;    
        case DMA_CHANNEL_1:
                DMA1CONbits.CHEN = 0;
                break;    
        case DMA_CHANNEL_2:
                DMA2CONbits.CHEN = 0;
                break;    
        case DMA_CHANNEL_3:
                DMA3CONbits.CHEN = 0;
                break;    
        default: break;
    }
}

inline static void DMA_TransferCountSet(DMA_CHANNEL channel, uint16_t transferCount)
{
    switch(channel) {
        case DMA_CHANNEL_0:
                DMA0CNT = transferCount;
                break;
        case DMA_CHANNEL_1:
                DMA1CNT = transferCount;
                break;
        case DMA_CHANNEL_2:
                DMA2CNT = transferCount;
                break;
        case DMA_CHANNEL_3:
                DMA3CNT = transferCount;
                break;
        default: break;
    }
}

inline static uint16_t DMA_TransferCountGet(DMA_CHANNEL channel)
    {
    switch(channel) {
            case DMA_CHANNEL_0:
                return (DMA0CNT);               
            case DMA_CHANNEL_1:
                return (DMA1CNT);               
            case DMA_CHANNEL_2:
                return (DMA2CNT);               
            case DMA_CHANNEL_3:
                return (DMA3CNT);               
        default: return 0;
    }
}

inline static void DMA_SoftwareTriggerEnable(DMA_CHANNEL channel )
{
    switch(channel) {
        case DMA_CHANNEL_0:
                DMA0REQbits.FORCE = 1;   
        case DMA_CHANNEL_1:
                DMA1REQbits.FORCE = 1;   
        case DMA_CHANNEL_2:
                DMA2REQbits.FORCE = 1;   
        case DMA_CHANNEL_3:
                DMA3REQbits.FORCE = 1;   
        default: break;
    }
}  
 
inline static void DMA_StartAddressASet(DMA_CHANNEL  channel, uint16_t address) 
{
    switch(channel) {
        case DMA_CHANNEL_0:
                DMA0STAL = address;
                DMA0STAH = 0;
                break;        
        case DMA_CHANNEL_1:
                DMA1STAL = address;
                DMA1STAH = 0;
                break;        
        case DMA_CHANNEL_2:
                DMA2STAL = address;
                DMA2STAH = 0;
                break;        
        case DMA_CHANNEL_3:
                DMA3STAL = address;
                DMA3STAH = 0;
                break;        
        default: break;
    }    
    }
    
inline static void DMA_StartAddressBSet(DMA_CHANNEL  channel, uint16_t address) 
{
    switch(channel) {
        case DMA_CHANNEL_0:
                DMA0STBL = address;
                DMA0STBH = 0;
                break;       
        case DMA_CHANNEL_1:
                DMA1STBL = address;
                DMA1STBH = 0;
                break;       
        case DMA_CHANNEL_2:
                DMA2STBL = address;
                DMA2STBH = 0;
                break;       
        case DMA_CHANNEL_3:
                DMA3STBL = address;
                DMA3STBH = 0;
                break;       
        default: break;
    }    
}
  
inline static uint16_t DMA_StartAddressAGet(DMA_CHANNEL  channel, uint16_t address) 
{    
    switch(channel) {
        case DMA_CHANNEL_0:
                address= DMA0STAL;       
                break;       
        case DMA_CHANNEL_1:
                address= DMA1STAL;       
                break;       
        case DMA_CHANNEL_2:
                address= DMA2STAL;       
                break;       
        case DMA_CHANNEL_3:
                address= DMA3STAL;       
                break;       
        default:
                address = 0;
                break;
    }
        return address;
            
}
 
 
inline static uint16_t DMA_StartAddressBGet(DMA_CHANNEL  channel, uint16_t address) {
        
    switch(channel) {
        case DMA_CHANNEL_0:
                address= DMA0STBL;       
                break;        
        case DMA_CHANNEL_1:
                address= DMA1STBL;       
                break;        
        case DMA_CHANNEL_2:
                address= DMA2STBL;       
                break;        
        case DMA_CHANNEL_3:
                address= DMA3STBL;       
                break;        
        default:
                address = 0;
                break;
    }
        return address;
}
  
 inline static void DMA_PeripheralAddressSet(DMA_CHANNEL channel, volatile unsigned int * address)
    {
    switch(channel) {
        case DMA_CHANNEL_0:
                DMA0PAD = (int)address;
                break;   
        case DMA_CHANNEL_1:
                DMA1PAD = (int)address;
                break;   
        case DMA_CHANNEL_2:
                DMA2PAD = (int)address;
                break;   
        case DMA_CHANNEL_3:
                DMA3PAD = (int)address;
                break;   
        default: break;
    }
}

inline static bool DMA_IsPeripheralWriteCollision(uint16_t dmaChannel )
{
    return DMAPWC & (1 << dmaChannel);
}

inline static bool DMA_IsRequestCollision(uint16_t dmaChannel )
{
    return DMARQC & (1 << dmaChannel);
}

inline static void DMA_PeripheralIrqNumberSet(DMA_CHANNEL channel, uint8_t irqNumber)
{
    switch(channel) {
        case DMA_CHANNEL_0:
                DMA0REQ = irqNumber;
                break;   
        case DMA_CHANNEL_1:
                DMA1REQ = irqNumber;
                break;   
        case DMA_CHANNEL_2:
                DMA2REQ = irqNumber;
                break;   
        case DMA_CHANNEL_3:
                DMA3REQ = irqNumber;
                break;   
        default: break;
    }
}


    
#endif  // DMA.h
